package com.bazaaroid.server.gae.core.dao.partner.impl;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import au.com.bytecode.opencsv.CSVReader;

import com.bazaaroid.server.gae.core.dao.impl.JDOGenericDAOImpl;
import com.bazaaroid.server.gae.core.dao.partner.LocationDAO;
import com.bazaaroid.server.gae.core.dao.partner.PartnerDAO;
import com.bazaaroid.server.gae.core.enums.Languages;
import com.bazaaroid.server.gae.core.ioc.GuiceFactory;
import com.bazaaroid.server.gae.core.persistence.model.partner.Address;
import com.bazaaroid.server.gae.core.persistence.model.partner.Location;
import com.bazaaroid.server.gae.core.persistence.model.partner.Partner;
import com.bazaaroid.server.gae.util.NumberUtil;
import com.google.appengine.api.datastore.GeoPt;
import com.google.appengine.api.datastore.Key;

public class JDOLocationDAOImpl extends JDOGenericDAOImpl<Location, Key>
		implements LocationDAO {

	@SuppressWarnings("unchecked")
	public List<Location> getLocationsByPartner(Partner partner) {
		PersistenceManager persistenceManager = getPersistenceManager();
		persistenceManager.setDetachAllOnCommit(true);

		Query query = persistenceManager.newQuery(getEntityClass());
		query.setFilter("partner == keyParam");
		query.declareImports("import com.google.appengine.api.datastore.Key;");
		query.declareParameters("Key keyParam");
		query.setOrdering("name asc");

		List<Location> locations = new ArrayList<Location>();

		try {
			locations = (List<Location>) query.execute(partner.getKey());
			locations.size();
		}
		finally {
			query.closeAll();
			persistenceManager.close();
		}

		return locations;
	}

	@Override
	public Location getLocationByPartnerAndLocalId(Partner partner,
			String localId) {
		PersistenceManager persistenceManager = getPersistenceManager();
		persistenceManager.setDetachAllOnCommit(true);

		Query query = persistenceManager.newQuery(getEntityClass());
		query.setFilter("partner == keyParam && localId == localIdParam");
		query.declareImports("import com.google.appengine.api.datastore.Key;");
		query.declareParameters("Key keyParam, String localIdParam");
		query.setUnique(true);

		Location location = null;

		try {
			location = (Location) query.execute(partner.getKey(), localId);
		}
		finally {
			query.closeAll();
			persistenceManager.close();
		}

		return location;
	}

	@Override
	public void importLocationsFromFile(String filePath) {
		PersistenceManager persistenceManager =  getPersistenceManager();
		CSVReader csvReader = null;

		PartnerDAO partnerDAO = GuiceFactory.getInjector().getInstance(PartnerDAO.class);
		Map<Key, Set<Key>> partnerLocations = new HashMap<Key, Set<Key>>();

		for(Partner p: partnerDAO.getAll()) {
			Set<Key> locationKeys = new HashSet<Key>();

			for(Location l: getLocationsByPartner(p))
				locationKeys.add(l.getKey());

			partnerLocations.put(p.getKey(), locationKeys);
		}

		try {
			InputStreamReader inputStreamReader = new InputStreamReader(
					new BufferedInputStream(new FileInputStream(filePath)), "UTF-8");

			csvReader = new CSVReader(inputStreamReader, ';', '\"', 2);

			Date today = new Date();
			String [] nextLine;

			while ((nextLine = csvReader.readNext()) != null) {
				int index = 0;

				String partnerName = nextLine[index++].trim();
				String localId = nextLine[index++].trim();
				String name = nextLine[index++].trim();
				String street = nextLine[index++].trim();
				String number = nextLine[index++].trim();
				String city = nextLine[index++].trim();
				String township = nextLine[index++].trim();
				String postalCode = nextLine[index++].trim();
				String country = nextLine[index++].trim();
				String state = nextLine[index++].trim();
				String latitudeStr = nextLine[index++].trim();
				String longitudeStr = nextLine[index++].trim();
				String openingHours = nextLine[index++].trim();
				String language = nextLine[index++].trim();

				Partner partner = partnerDAO.getPartnerByName(partnerName);

				if(partner != null) {
					Location location = getLocationByPartnerAndLocalId(
							partner, localId);

					if(location == null) {
						location = new Location();
						location.setLocalId(localId);
						location.setCreated(today);
					}
					else
						partnerLocations.get(partner.getKey())
							.remove(location.getKey());

					if(Languages.isSupportedLanguage(language))
						location.setLanguage(language);
					else
						location.setLanguage(null);

					location.setModified(today);
					location.setName(name);
					location.setOpeningHours(openingHours);

					Address address = new Address();
					address.setStreet(street);
					address.setNumber(number);
					address.setCity(city);
					address.setTownship(township);
					address.setPostalCode(postalCode);
					address.setCountry(country);
					address.setState(state);
					location.setAddress(address);

					Float latitude = NumberUtil.stringToFloat(latitudeStr);
					Float longitude = NumberUtil.stringToFloat(longitudeStr);
					location.setGeoPoint(latitude != null && longitude != null
						? new GeoPt(latitude, longitude) : null);

					partner = persistenceManager.getObjectById(
							Partner.class, partner.getKey());
					partner.addLocation(location);
				}
			}
			csvReader.close();

			for(Key partnerKey: partnerLocations.keySet()) {
				Set<Key> locationKeys = partnerLocations.get(partnerKey);
				if(!locationKeys.isEmpty())
					deleteAll(locationKeys);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			persistenceManager.close();
		}
	}
}
